﻿using GKQC.Common;
using GKQC.DbHelper.Dao;
using GKQC.DbHelper.DbModels;
using GKQC.DbHelper.ErpDbModels;
using GKQC.DbHelper.ViewModels;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GKQC.DbHelper.Services
{
    public class OqcService
    {
        AllDbContext dbContext;

        public OqcService(AllDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public List<OqcDataModel> GetDatas(long headId)
        {
            return dbContext.QcDb.Queryable<OqcDataModel>()
                .Where(d => d.HeadId == headId)
                .ToList();
        }

        public List<OqcHeadModel> GetHeadsByLotNo(string lotNo)
        {
            var v = dbContext.QcDb.Queryable<OqcHeadModel>().Where(o => o.LotNo == lotNo);
            if (v != null)
                return v.ToList();
            else return new List<OqcHeadModel>();
        }

        /// <summary>
        /// 取最近的一条记录
        /// </summary>
        /// <param name="lotNo"></param>
        /// <returns></returns>
        public OqcHeadModel GetHeadByLotNo(string lotNo)
        {
            var v = dbContext.QcDb.Queryable<OqcHeadModel>().Where(o => o.LotNo == lotNo)
                .OrderBy(o=>o.CreateDate, OrderByType.Desc);
            if (v != null && v.Count()>0)
                return v.First();
            else return null;
        }

        public OqcHeadModel GetHeadById(long id)
        {
            var heads = dbContext.QcDb.Queryable<OqcHeadModel>().Where(o => o.Id == id);
            if (heads != null && heads.Count() > 0)
                return heads.First();
            else
                return null;
        }

        public List<OqcHeadModel> GetHeads(int count)
        {
            return dbContext.QcDb.Queryable<OqcHeadModel>()
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .Take(count).ToList();
        }

        public OqcHeadModel GetHead(string customerCode,string pn)
        {
            return dbContext.QcDb.Queryable<OqcHeadModel>()
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .Where(t => t.CustomerCode == customerCode && t.Pn == pn)
                .ToList().FirstOrDefault();
        }

        public void GetDtls(OqcHeadModel head)
        {
            var dtls = dbContext.QcDb.Queryable<OqcDtlModel>()
                .Where(o => o.HeadId == head.Id);
            if (dtls != null && dtls.Count() > 0)
                head.Dtls = dtls.ToList();

            if(head.Dtls != null && head.Dtls.Count >0)
            {
                for(int i=0;i<head.Dtls.Count;i++)
                {
                    head.Dtls[i].Item = head.Dtls[i].GetItem(i);
                }
            }
        }

        public int Save(OqcHeadModel head)
        {
            int i = 0;

            bool isNew = false;
            try
            {
                dbContext.QcDb.Ado.BeginTran();

                if (head.Id <= 0)
                {
                    if (!dbContext.QcDb.Insertable(head).ExecuteCommandIdentityIntoEntity())
                        throw new Exception("U0001: 新增保存出錯");

                    isNew = true;
                }

                List<OqcDataModel> datas = new List<OqcDataModel>();
                dbContext.QcDb.Deleteable<OqcDataModel>()
                    .Where(o => o.HeadId == head.Id)
                    .ExecuteCommand();

                if (head.ElectricViewModels != null && head.ElectricViewModels.Count > 0)
                {
                    datas.AddRange(ViewModelTrans<OqcDataModel>.ElectricViewToData(head.Id, head.SourceSNo, head.ElectricViewModels));
                }
                if (head.SizeViewModels != null && head.SizeViewModels.Count > 0)
                {
                    datas.AddRange(ViewModelTrans<OqcDataModel>.SizeViewToData(head.Id, head.SourceSNo, head.SizeViewModels));
                }

                var overLengths = datas.Where(d => d.Value > 9999999999);
                if (overLengths != null && overLengths.Count() > 0)
                    overLengths.ToList().ForEach(o => o.Value = 9999999999);
                var overLengths2 = datas.Where(d => d.Value < -9999999999);
                if (overLengths2 != null && overLengths2.Count() > 0)
                    overLengths2.ToList().ForEach(o => o.Value = -9999999999);

                if (datas.Count > 0)
                    dbContext.QcDb.Insertable(datas)
                    .ExecuteCommand();
                if(isNew)
                {
                    head.Dtls.ForEach(d => d.HeadId = head.Id);
                    dbContext.QcDb.Insertable(head.Dtls).ExecuteCommand();
                }
                else
                {
                    if(head.Dtls.Count> 0 && head.Dtls.Where(d=>d.HeadId<=0).Count()>0)
                    {
                        head.Dtls.ForEach(d => d.HeadId = head.Id);
                        dbContext.QcDb.Insertable(head.Dtls).ExecuteCommand();
                    }
                    else
                       dbContext.QcDb.Updateable(head.Dtls).ExecuteCommand();
                }
                if (!isNew)
                    i = dbContext.QcDb.Updateable(head)
                        .ExecuteCommand();
                else
                    i = 1;

                dbContext.QcDb.Ado.CommitTran();
                head.Datas.Clear();
                head.Datas.AddRange(datas);
            }
            catch (Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }

            return i;
        }

        /// <summary>
        /// 複製，不包含檢測數據
        /// </summary>
        /// <param name="OqcHeadModel"></param>
        /// <returns></returns>
        public OqcHeadModel Clone(OqcHeadModel OqcHeadModel)
        {
            OqcHeadModel newModel;
            if (OqcHeadModel == null)
                newModel = new OqcHeadModel();
            else newModel = ClassClone<OqcHeadModel, OqcHeadModel>.Clone(OqcHeadModel);
            newModel.Id = 0;
            newModel.ModiDate = null;
            newModel.ModiUser = string.Empty;

            return newModel;
        }

        /// <summary>
        /// 審核
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int Approve(List<OqcHeadModel> ortList)
        {
            int i = 0;
            i = dbContext.QcDb.Updateable(ortList)
                .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate })
                .ExecuteCommand();
            return i;
        }


        /// <summary>
        /// 反審核
        /// </summary>
        /// <param name="headList"></param>
        /// <returns></returns>
        public int UnApprove(List<OqcHeadModel> headList)
        {
            int i = 0;
            if (headList != null && headList.Count > 0)
            {
                i = dbContext.QcDb.Updateable(headList)
                    .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate})
                    .ExecuteCommand();
            }
            return i;
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="heads"></param>
        /// <returns></returns>
        public int Delete(List<OqcHeadModel> heads)
        {
            int i = 0;
            try
            {
                dbContext.QcDb.Ado.BeginTran();
                dbContext.QcDb.Deleteable<OqcDataModel>()
                    .In(it => it.HeadId, heads.Select(o => o.Id).ToArray())
                    .ExecuteCommand();
                i = dbContext.QcDb.Deleteable(heads)
                    .ExecuteCommand();
                dbContext.QcDb.Ado.CommitTran();
            }
            catch(Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }
            return i;
        }

        public List<OqcHeadModel> Query(OqcFilter filter)
        {
            if (filter == null) return GetHeads(100);

            return dbContext.QcDb.Queryable<OqcHeadModel>()
                .WhereIF(!string.IsNullOrWhiteSpace(filter.SourceNo), t => t.SourceNo == filter.SourceNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.SourceNo) && filter.SourceSNo>0
                    , t => t.SourceSNo == filter.SourceSNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.LotNo), t => t.LotNo == filter.LotNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Customer), t => t.Customer == filter.Customer)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Pn), t => t.Pn == filter.Pn)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Series), t => t.Series == filter.Series)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Spec), t => t.Spec == filter.Spec)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Size), t => t.Size == filter.Size)
                .WhereIF(filter.IsTestDate, t => t.TestDate >= filter.StartTestDate.Date)
                .WhereIF(filter.IsTestDate, t => t.TestDate < filter.EndTestDate.AddDays(1).Date)
                .WhereIF(filter.ReportId > 0, t => t.ReportId == filter.ReportId)
                .WhereIF(filter.IsApprove && !filter.IsUnApprove, t => !SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(!filter.IsApprove && filter.IsUnApprove, t => SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(filter.IsModiDate, t => t.ModiDate >= filter.StartModiDate.Date)
                .WhereIF(filter.IsModiDate, t => t.ModiDate < filter.EndModiDate.AddDays(1).Date)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .Take(filter.RowCount).ToList();
        }

        public void GenStandard(OqcHeadModel head)
        {
            try
            {
                int capNum = ProductCode.GetCapStandardNum(head.GetCap());

                try
                {
                    List<qcd_view> standards = ErpService.GetOqcQcd(dbContext, head.Pn, head.CustomerCode);
                    List<ItemCodeTran> _ItemCodeTrans = null;
                    ItemCodeTranService.GetItemCodeTran(dbContext, _ItemCodeTrans);
                    ItemCodeTranService.TranItemCodeFromErp(_ItemCodeTrans, standards);
                    

                    foreach (qcd_view qcd in standards)
                    {
                        if (qcd.ItemCode == "DF" && head.DfMax <= 0)
                        {
                            head.DfMax = qcd.qcd062;
                            head.Standard.DfMax = head.DfMax;
                        }
                        else if (qcd.ItemCode == "CAP")
                        {
                            double cap = head.GetCap();
                            if (cap > 0 && head.CapMax == 0)
                            {
                                head.Standard.CapMax = qcd.qcd062;
                                head.Standard.CapMin = qcd.qcd061;
                                head.CapMax = Math.Round((qcd.qcd062 - cap) / cap * 100, 0);
                                head.CapMin = Math.Round((cap - qcd.qcd061) / cap * 100, 0);
                            }
                        }
                        else if (qcd.ItemCode == "LC" && head.LcMax <= 0)
                        {
                            head.LcMax = qcd.qcd062;
                        }
                        else if (qcd.ItemCode == "ESR" && head.EsrMax <=0)
                            head.EsrMax = qcd.qcd062;
                        else if (qcd.ItemCode == "Z" && head.ZMax<=0)
                            head.ZMax = qcd.qcd062;
                        else if (qcd.ItemCode == "D")
                        {
                            head.DMax = qcd.qcd062;
                            head.Standard.DMax = qcd.qcd062;
                            head.Standard.DMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "L")
                        {
                            head.LMax = qcd.qcd062;
                            head.Standard.LMax = qcd.qcd062;
                            head.Standard.LMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "H")
                        {
                            head.Standard.HMax = qcd.qcd062;
                            head.Standard.HMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "L1")
                        {
                            head.Standard.L1Max = qcd.qcd062;
                            head.Standard.L1Min = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "L2")
                        {
                            head.Standard.L2Max = qcd.qcd062;
                            head.Standard.L2Min = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "P")
                        {
                            head.Standard.PMax = qcd.qcd062;
                            head.Standard.PMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "cp")
                        {
                            head.Standard.cpMax = qcd.qcd062;
                            head.Standard.cpMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "W")
                        {
                            head.Standard.WMax = qcd.qcd062;
                            head.Standard.WMin = qcd.qcd061;
                        }
                        else if (qcd.ItemCode == "C")
                        {
                            head.Standard.CMax = qcd.qcd062;
                            head.Standard.CMin = qcd.qcd061;
                        }
                    }
                }
                catch(Exception ex)
                {
                    Logger.LogError(ex);
                }

                if(head.Standard.DfMax ==0 && head.DfMax>0) head.Standard.DfMax = head.DfMax;
                if (head.Standard.CapMax == 0)
                {
                    head.Standard.CapMax = Math.Round(head.GetCap() * (1 + head.CapMax / 100), capNum);
                    head.Standard.CapMin = Math.Round(head.GetCap() * (1 + head.CapMin / 100), capNum); //head.CapMin;
                }
                head.Standard.LcMax = head.LcMax;
                head.Standard.ZMax = head.ZMax;
                head.Standard.EsrMax = head.EsrMax;
                head.Standard.DMax = head.DMax;

                if (head.Standard.L1Max == 0 && head.L1 > 0.5)
                {
                    head.Standard.L1Max = head.L1 + 0.5;
                    head.Standard.L1Min = head.L1 - 0.5;
                }
                if (head.Standard.L2Max == 0 && head.L2 > 0.5)
                {
                    head.Standard.L2Max = head.L2 + 0.5;
                    head.Standard.L2Min = head.L2 - 0.5;
                }


                if (head.Standard.DMax <=0)
                {
                    double D = ProductCode.GetD(head.Pn);
                    if(D>0) head.DMax = D + 0.5;
                    head.Standard.DMax = head.DMax;
                }
                head.Standard.LMax = head.LMax;
                if(head.Standard.LMax <= 0)
                {
                    double L = ProductCode.GetL(head.Pn);
                    if(L>0)  head.LMax = ProductCode.GetLMax(head.Pn, head.CustomerCode);
                    head.Standard.LMax = head.LMax;
                }

                if (head.Standard.PMax == 0)
                {
                    double p = 0;
                    if (double.TryParse(head.Pitch, out p))
                    {
                        if (p > 0)
                        {
                            if (!string.IsNullOrWhiteSpace(head.Pn) && head.Pn.Length > 19 && head.Pn.Substring(head.Pn.Length - 4, 1) == "P"
                                && (head.CustomerCode == "0096" || head.CustomerCode == "0210" || head.CustomerCode == "1012")
                                )
                            {
                                head.Standard.PMax = p + 0.8;
                                head.Standard.PMin = p - 0.2;
                            }
                            else
                            {
                                head.Standard.PMax = p + 0.5;
                                head.Standard.PMin = p - 0.5;
                            }
                        }
                    }
                }

                if(head.Standard.CMax == 0)
                {
                    double cp = ProductCode.GetMakeTypeValue(ProductCode.GetMakeCode(head.Pn));
                    if (cp > 4) head.Standard.CMax = cp + 0.5;
                }

                if(head.Standard.cpMax == 0 && head.cp > 0)
                {
                    head.Standard.cpMax = head.cp + 0.05;
                    head.Standard.cpMin = head.cp - 0.05;
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                //throw ex;
            }
        }

        public void GenAql(OqcHeadModel head)
        {
            double qty0, qty004, qty01, accept0, accept004, accept01, reject0, reject004, reject01;
            Tools.GetAQL(head.Qty, out qty0, out qty004, out qty01
                , out accept0, out accept004, out accept01
                , out reject0, out reject004, out reject01
                , head.CustomerCode
                );


            head.AqlQty0 = qty0;
            head.AqlQty004 = qty004;
            head.AqlQty01 = qty01;

            head.AqlAcceptQty0 = accept0;
            head.AqlAcceptQty004 = accept004;
            head.AqlAcceptQty01 = accept01;

            head.AqlRejectQty0 = reject0;
            head.AqlRejectQty004 = reject004;
            head.AqlRejectQty01 = reject01;
        }

        public void CancelUploadToErp(List<OqcHeadModel> approveList)
        {
            if (approveList == null || approveList.Count == 0) return;

            foreach (OqcHeadModel head in approveList)
            {
                ErpService.CancelOqcErpData(dbContext, head.SourceNo);
            }
        }
        public void UploadToErp(List<OqcHeadModel> approveList, out string msg)
        {
            msg = string.Empty;
            if (approveList == null || approveList.Count == 0) return;
            List<ItemCodeTran> trans = dbContext.QcDb.Queryable<ItemCodeTran>().ToList();
            if (!trans.Any())
            {
                msg = "未設置ERP檢測項目對照表t_sys_itemcode";
                return;
            }
            foreach (OqcHeadModel head in approveList)
            {
                if (head.Datas == null) continue;
                if (head.Datas.Count == 0)
                    head.Datas.AddRange(GetDatas(head.Id));
                List<tc_qdf_file> qdf = OqcDataToErpData(head, trans);
                if (qdf.Count == 0) continue;
                int i = ErpService.SaveData(dbContext, qdf);
                if (i > 0) msg = "上傳ERP成功";
            }
        }

        /// <summary>
        /// OQC测试数据转换为ERP数据,没有对照表的不上传
        /// </summary>
        /// <param name="head"></param>
        /// <param name="ItemCodeTrans">检测项目代号对照表</param>
        /// <returns></returns>
        public static List<tc_qdf_file> OqcDataToErpData(OqcHeadModel head, List<ItemCodeTran> ItemCodeTrans)
        {
            List<tc_qdf_file> erpDatas = new List<tc_qdf_file>();
            if (string.IsNullOrWhiteSpace(head.SourceNo) || ItemCodeTrans == null || ItemCodeTrans.Count == 0) return erpDatas;

            if (head.Datas == null || head.Datas.Count == 0)
                return erpDatas;

            foreach (OqcDataModel oqc in head.Datas)
            {
                string erpItemCode = string.Empty;
                var tran = ItemCodeTrans.Where(t => t.ItemCode == oqc.ItemCode && t.ErpItemCode.StartsWith("O")).FirstOrDefault();
                if (tran == null) continue;
                tc_qdf_file qdf = new tc_qdf_file();
                qdf.tc_qdf01 = head.SourceNo;
                qdf.tc_qdf02 = tran.ErpItemCode;
                qdf.tc_qdf03 = oqc.Value;
                qdf.tc_qdf04 = oqc.Id;
                qdf.tc_qdf05 = oqc.Value == 0 ? oqc.Valid : string.Empty;
                qdf.tc_qdfacti = "Y";
                erpDatas.Add(qdf);
            }

            return erpDatas;
        }
    }
}
